#include "type.h"
PROC proc[NPROC]; 
PROC *freeList;
PROC *readyQueue; 
PROC *running;

#include "queue.c"
int kfork()
{
    int i;
    PROC *p = dequeue(&freeList); 
    if (!p)
    {
        printf("no more proc\n");
        return(-1);
    }
    p->status = READY;
    p->priority = 1;	// ALL PROCs priority=l,except PO
    p->ppid = running->pid;
    for ( i = 1; i < 10; i++)
    {
        p->kstack[SSIZE - i] = 0; 
    }   
    p->kstack[SSIZE-1] = (int)body();
    p->ksp = &(p->kstack[SSIZE - 9]);
    enqueue(&readyQueue, p); 
    return p->pid;
}
int kexit()
{
    running->status = FREE; 
    running->priority = 0; 
    enqueue(&freeList, running);
    printList("freeList", freeList); 
    tswitch();
}
int do_kfork()
{
    int child = kfork();
    if (child < 0)
        printf("kfork failed\n");
    else
    {
        printf("proc %d kforked a child = %d\n", running->pid, child); 
        printList("readyQueue", readyQueue);
    }
    return child;
}

int do_switch()
{
    tswitch();
}
int do_exit()
{
    kexit();
}
    
int body()	// process body function
{
    int c;
    printf("proc %d starts from body()\n", running->pid); 
    while(1)
    { 
        printf("***************************************\n");
        printf("proc %d running: parent=%d\n", running->pid,running->ppid);
        printf("enter a key [f|s|q] :");
        c = getchar();
        getchar();
        switch(c)
        {
            case 'f': do_kfork ();      break;
            case 's': do_switch();      break;
            case 'q': do_exit();        break;
        }
    }
}
// initialize the MT system�� 
int init()
{
    int i;
    PROC *p;
    for (i=0; i<NPROC; i++)
    {
        p = &proc[i];
        p->pid = i;
        p->status = FREE; 
        p->priority = 0; 
        p->next = p+1;
    }
    proc[NPROC-1].next = 0;
    freeList = &proc[0]; 
    readyQueue = 0; 
    // create PO as the initial
    p = running = dequeue(&freeList); // use proc[0] p->status = READY;
    p->ppid = 0;	// PO is its own parent
    printList("freeList", freeList);
    printf("init complete: P0 running\n");
}

//running process
int main()
{
    printf("Welcome to the MT Multitasking System\n"); 
    init();	//
    kfork();	//
    while(1)
    {
        printf("PO:switch process\n");
        if (readyQueue)
        tswitch();
    }
}

/*********** scheduler *************/
int scheduler()
{
    printf("proc %d in scheduler()\n", running->pid); 
    if (running->status == READY)
        enqueue(&readyQueue, running);
    printList("readyQueue", readyQueue);
    running = dequeue(&readyQueue);
    printf("next running = %d\n", running->pid);
}